package club.calong.sanniu.service;

import club.calong.sanniu.http.request.UserRequest;
import club.calong.sanniu.http.response.ListResponseData;
import club.calong.sanniu.http.response.UserResponseData;
import club.calong.sanniu.pojo.Permission;
import club.calong.sanniu.pojo.Role;
import club.calong.sanniu.pojo.User;
import club.calong.sanniu.repository.AdminRepository;
import club.calong.sanniu.repository.PermissionRepository;
import club.calong.sanniu.repository.RoleRepository;
import club.calong.sanniu.util.CacheUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class AdminService {

    AdminRepository repository;

    PermissionRepository permissionRepository;

    RoleRepository roleRepository;

    PasswordEncoder passwordEncoder;

    @Value("${app.user.role-id}")
    String USER_ROLE_ID;

    @Autowired
    public AdminService(AdminRepository repository,
                        PermissionRepository permissionRepository,
                        RoleRepository roleRepository,
                        PasswordEncoder passwordEncoder) {

        this.repository = repository;
        this.roleRepository = roleRepository;
        this.permissionRepository = permissionRepository;
        this.passwordEncoder = passwordEncoder;
    }

    public UserResponseData info(String token) {

        String username = CacheUtils.getCache().get(token);
        if (username != null) {
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.eq(User.USERNAME, username);
            User user = repository.selectOne(wrapper);
            setUserRoles(user);
            setUserPermissions(user);
            return convertUserResponseData(user);
        } else {
            return null;
        }
    }

    private void setUserRoles (User user) {

        QueryWrapper<Role> wrapper = new QueryWrapper<>();
        wrapper.in(Role.ID, user.getRoles());
        List<Role> roles = roleRepository.selectList(wrapper);
        roles.forEach(item -> {
            user.getRoles().add(item.getId());
            user.getRoleNames().add(item.getName());
            user.getPermissions().addAll(item.getPermissions());
        });
    }

    private void setUserPermissions (User user) {

        QueryWrapper<Permission> wrapper = new QueryWrapper<>();
        wrapper.in(Permission.ID, user.getPermissions());
        List<Permission> permissions = permissionRepository.selectList(wrapper);
        Set<String> permissionNames = new HashSet<>(permissions.size());
        permissions.forEach(item -> {
            permissionNames.add(item.getName());
        });
        user.setPermissionNames(permissionNames);
    }

    private UserResponseData convertUserResponseData (User user) {

        UserResponseData result = new UserResponseData();
        if (user != null) {
            result.setName(user.getName());
            result.setAvatar(user.getAvatar());
            result.setIntroduction(user.getIntroduction());
            result.setRoles(user.getRoleNames());
        }
        return result;
    }

    public ListResponseData<User> page(Integer current, Integer size, boolean user) {

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        if (user)
            wrapper.eq(User.ROLE_NAME, USER_ROLE_ID);
        else
            wrapper.ne(User.ROLE_NAME, USER_ROLE_ID);

        wrapper.orderByDesc(User.ID);
        Page<User> page = repository.selectPage(new Page<>(current, size), wrapper);
        List<User> userList = page.getRecords();
        userList.forEach(this::setUserRoles);
        return new ListResponseData<>(userList, page.getTotal());
    }

    @Value("${app.avatar.admin}")
    String ADMIN_AVATAR;

    public boolean create(UserRequest user) {

        user.setAvatar(ADMIN_AVATAR);
        user.setIntroduction("管理员");
        user.setId(null);
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        return repository.insert(convertUser(user)) == 1;
    }

    public User convertUser (UserRequest request) {
        User user = new User();

        user.setId(request.getId());
        user.setAvatar(request.getAvatar());
        user.setIntroduction(request.getIntroduction());
        user.setName(request.getName());
        user.setUsername(request.getUsername());
        user.setPassword(request.getPassword());
        user.setRoles(request.getRoles());
        user.setEmail(request.getEmail());
        user.setActivated(request.getActivated());
        user.setPassword(passwordEncoder.encode(request.getPassword()));
        return user;
    }

    public boolean update(UserRequest user) {

        return repository.updateById(convertUser(user)) == 1;
    }

    public boolean delete(Integer id) {

        return repository.deleteById(id) == 1;
    }
}
